#include "Logic.h"

Logic::Logic() {}

Logic::~Logic() {}

// sets up the program before user begins using it
// populates the internal vector with tasks from files
void Logic::setup() {
	
	setupMainWriter();

	// 10 different undo states
	// it will be cycled when a command is successfully invoked
	setupWriters();
	setInitUndoState(INIT_UNDO_STATE);
	populateData();
}

// this is the public function for UI to call
// all logic is done in SLAP
// scroll down to see how the sub-functions are implemented
string Logic::executeUserCommand(string userCommand, vector<Task>& tasksVector) {
	Parser::PARSED_COMMAND parsedCommand;
	Parser::CommandType commandType;

	string statusMessage;

	parsedCommand = _parser.parseUserCommand(userCommand);
	commandType = parsedCommand.commandType;

	if( commandType == Parser::ADD_FLOATING_TASK ) {
		statusMessage = addFloatingTask(parsedCommand, tasksVector);
	} else if( commandType == Parser::ADD_DEADLINE_TASK ) {
		statusMessage = addDeadlineTask(parsedCommand, tasksVector);
	} else if( commandType == Parser::ADD_TIMED_TASK ) {
		// statusMessage = addTimedTask(parsedCommand, tasksVector);
//	} else if( commandType == Parser::CommandType::DELETE_TASK ) {
//		statusMessage = deleteTask(parsedCommand, tasksVector);
	} else if( commandType == Parser::LIST_ALL ) {
		statusMessage = listAllTasks(parsedCommand, tasksVector);
	} else if( commandType == Parser::LIST_MONTH ) {
		statusMessage = listTaskByMonth(parsedCommand, tasksVector);
	} else if( commandType == Parser::LIST_DAY ) {
		statusMessage = listTaskByDay(parsedCommand, tasksVector);
	} else if( commandType == Parser::LIST_WEEK ) {
		statusMessage = listTaskNextWeek(parsedCommand, tasksVector);
	} else if( commandType == Parser::LIST_SEARCH_TERM ) {
		statusMessage = listTaskBySearchTerm(parsedCommand, tasksVector);
	} else if( commandType == Parser::EDIT_RENAME ) {
		statusMessage = editTaskByName(parsedCommand, tasksVector);
	} else if( commandType == Parser::EDIT_START_TIME || commandType == Parser::EDIT_END_TIME ) {
		statusMessage = editTaskByTime(parsedCommand, tasksVector);
	} else if( commandType == Parser::EDIT_START_DATETIME || commandType == Parser::EDIT_END_DATETIME ) {
		statusMessage = editTaskByDateTime(parsedCommand, tasksVector);
	} else if( commandType == Parser::SORT_ALPHABET ) {
		statusMessage = sortTasksAlphabetically(parsedCommand, tasksVector);
	} else if( commandType == Parser::SORT_COMPLETED ) {
		statusMessage = sortTasksByDone(parsedCommand, tasksVector);
	} else if( commandType == Parser::SORT_FLAG ) {
		statusMessage = sortTasksByFlag(parsedCommand, tasksVector);
	} else if( commandType == Parser::SORT_TIME ) {
		statusMessage = sortTasksByDateTime(parsedCommand, tasksVector);
//	} else if( commandType == Parser::CommandType::CLEAR_TASK ) {
//		statusMessage = clearTask();
//	} else if( commandType == Parser::EXIT ) {
//		exit(1); // let UI handle the quit by returning a statusMessage
	}

	updateUndoState();

	return statusMessage;
}

// HOW THE FUNCTIONS GENERALLY WORK //

// 1.  if required, empty UI's display vector
// 2. invoke execution e.g. _data.executeAdd
// 3. update Data's internal data
// 4. update UI's display
// 5. return statusMessage
// 6. write updated contents to file
// 7. update undo state
// 8. if failure, log errors

// END SECTION: HOW THE FUNCTIONS GENERALLY WORK //


// FUNCTIONS BELOW ARE PRIVATE SUB-FUNCTIONS //

string Logic::addFloatingTask(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	
	string statusMessage;
	Data::DataFeedback dataFeedback;
	
	// empty UI's display
	emptyTasksVector(tasksVector);

	// set _task attributes
	string taskName = parsedCommand.addTaskName;
	ptime startTime = parsedCommand.addStartTime;
	ptime endTime = parsedCommand.addEndTime;

	// task creation
	_task = Task(taskName, 0, Task::FLOATING, false, 0, startTime, endTime);

	// add into internal data
	dataFeedback = _data.executeAdd(_task);

	// update UI's display
	tasksVector.push_back(_task);

	// return status message to UI
	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = ADD_SUCCESS_MESSAGE;
		vector<Task> tasks;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = ADD_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::addDeadlineTask(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	
	string statusMessage;
	Data::DataFeedback dataFeedback;

	// empty UI's display
	emptyTasksVector(tasksVector);

	// set _task attributes
	string taskName = parsedCommand.addTaskName;
	ptime startTime = parsedCommand.addStartTime;
	ptime endTime = parsedCommand.addEndTime;

	// task creation
	_task = Task(taskName, 0, Task::DEADLINE, false, 0, startTime, endTime);

	// add to internal data
	dataFeedback = _data.executeAdd(_task);

	// update UI's display
	tasksVector.push_back(_task);

	// return status message to UI
	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = ADD_SUCCESS_MESSAGE;
		vector<Task> tasks;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = ADD_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

bool Logic::isExistName(Parser::PARSED_COMMAND parsedCommand) {

	return false;
}

bool Logic::isDateClash(Parser::PARSED_COMMAND parsedCommand) {

	return false;
}


string Logic::deleteTask(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;
	DeleteType deleteType;
	
	deleteType = determineDeleteType(parsedCommand);

	switch( deleteType ) {
	case INDEX:
		statusMessage = deleteTaskByIndex(parsedCommand, tasksVector);
		break;
	case DONE:
		statusMessage = deleteDoneTask(parsedCommand, tasksVector);
		break;
	case NAME:
		statusMessage = deleteTaskByName(parsedCommand, tasksVector);
		break;
	case SEARCH_TERM:
		statusMessage = deleteTaskBySearchTerm(parsedCommand, tasksVector);
		break;
	default:
		statusMessage = NOT_FOUND_ERROR_MESSAGE;
		break;
	}

	return statusMessage;
}

Logic::DeleteType Logic::determineDeleteType(Parser::PARSED_COMMAND parsedCommand) {

	DeleteType deleteType;
	string term;
	bool typeIndex;
	bool typeDone;
	bool typeName;
	bool typeSearchTerm;

	term = parsedCommand.addTaskName;

	typeIndex = isDeleteByIndex(term);
	typeDone = isDeleteByDone(term);
	typeName = isDeleteByName(term);
	typeSearchTerm = isDeleteBySearchTerm(term);

	if( typeIndex && !typeDone && !typeName && !typeSearchTerm ) {
		deleteType = INDEX;
	} else if( !typeIndex && typeDone && !typeName && !typeSearchTerm ) {
		deleteType = DONE;
	} else if( !typeIndex && !typeDone && typeName && !typeSearchTerm ) {
		deleteType = NAME;
	} else if( !typeIndex && !typeDone && !typeName && typeSearchTerm ) {
		deleteType = SEARCH_TERM;
	}

	return deleteType;
}

// this function determines whether it deletes by index or
// by one of the following 3: name, searchTerm, done
// returns TRUE if deleteType is and INTEGER
// returns FALSE if deleteType is a STRING
bool Logic::isDeleteByIndex(string term) {

	bool isDeleteTypeIndex;

	string::const_iterator csit = term.begin();
	while( csit != term.end() && isdigit(*csit) ) {
		csit++;
	}
	
	if( !term.empty() && csit==term.end() ) {
		isDeleteTypeIndex = true;
	} else {
		isDeleteTypeIndex = false;
	}

	return isDeleteTypeIndex;
}

// this function determines whether it deletes by done
// returns TRUE if term matches keyword done
// returns FALSE otherwise
bool Logic::isDeleteByDone(string term) {
	
	bool isDeleteTypeDone;
	if( term == DELETE_TYPE_DONE ) {
		isDeleteTypeDone = true;
	} else {
		isDeleteTypeDone = false;
	}

	return isDeleteTypeDone;
}

bool Logic::isDeleteByName(string term) {

	bool isDeleteTypeName;

	vector<Task> tasks;
	_data.getByName(tasks, term);

	if( tasks.empty() ) {
		isDeleteTypeName = false;
	} else {
		isDeleteTypeName = true;
	}

	return isDeleteTypeName;
}

bool Logic::isDeleteBySearchTerm(string term) {

	bool isDeleteSearchTerm;

	vector<Task> tasks;
	_data.getBySearchTerm(tasks, term);

	if( tasks.empty() ) {
		isDeleteSearchTerm = false;
	} else {
		isDeleteSearchTerm = true;
	}

	return isDeleteSearchTerm;
}

string Logic::deleteTaskByIndex(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	Data::DataFeedback dataFeedback;

	string statusMessage;
	
	int index = parsedCommand.deleteTaskID;

	int taskId = tasksVector[index].getTaskID();

	dataFeedback = _data.executeDeleteTaskID(taskId);

	if(dataFeedback == Data::SUCCESS ) {
		statusMessage = DELETE_SUCCESS_MESSAGE;
		vector<Task> tasks;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = DELETE_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::deleteTaskByName(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;
	string taskName;
	int taskId;
	Data::DataFeedback dataFeedback;

	taskName = parsedCommand.addTaskName;

	vector<Task> tasks;

	// insert try catch block here
	dataFeedback = _data.getByName(tasks ,taskName);
	
	while ( !tasks.empty() ) {
		taskId = tasks.back().getTaskID();
		dataFeedback = _data.executeDeleteTaskID(taskId);
		// record all tasks deleted
		// record all tasks not deleted
		tasks.pop_back();
	}

	if(dataFeedback == Data::SUCCESS ) {
		statusMessage = DELETE_SUCCESS_MESSAGE;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = DELETE_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::deleteTaskBySearchTerm(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	
	string statusMessage;
	string searchTerm;
	int taskId;
	Data::DataFeedback dataFeedback;

	searchTerm = parsedCommand.deleteSearchTerm;

	vector<Task> tasks;

	// insert try catch block here
	dataFeedback = _data.getBySearchTerm(tasks, searchTerm);

	while ( !tasks.empty() ) {
		taskId = tasks.back().getTaskID();
		dataFeedback = _data.executeDeleteTaskID(taskId);
		// record all tasks deleted
		// record all tasks not deleted
		tasks.pop_back();
	}

	if(dataFeedback == Data::SUCCESS ) {
		statusMessage = DELETE_SUCCESS_MESSAGE;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = DELETE_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::deleteDoneTask(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;
	int taskId;
	Data::DataFeedback dataFeedback;

	vector<Task> tasks;

	dataFeedback = _data.getByDone(tasks);
	
	while( !tasks.empty() ) {
		taskId = tasks.back().getTaskID();
		_data.executeDeleteTaskID(taskId);
		tasks.pop_back();
	}

	if(dataFeedback == Data::SUCCESS ) {
		statusMessage = DELETE_SUCCESS_MESSAGE;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = DELETE_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::listAllTasks(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	
	string statusMessage;
	Data::DataFeedback dataFeedback;

	vector<Task> tasks;
	dataFeedback = _data.getAll(tasks);

	emptyTasksVector(tasksVector);

	// copies tasks from _data to tasksVector
	for( unsigned int i=0; i<tasks.size(); i++ ) {
		tasksVector.push_back(tasks[i]);
	}

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = LIST_SUCCESS_MESSAGE;
		_writer.write(tasks);
	} else {
		statusMessage = LIST_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::listTaskBySearchTerm(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	
	string statusMessage;
	string searchTerm;
	Data::DataFeedback dataFeedback;

	searchTerm = parsedCommand.listSearchTerm;
	vector<Task> tasks;
	
	dataFeedback = _data.getBySearchTerm(tasks, searchTerm);

	emptyTasksVector(tasksVector);

	for( unsigned int i=0; i<tasks.size(); i++ ) {
		tasksVector.push_back(tasks[i]);
	}

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = LIST_SUCCESS_MESSAGE;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = LIST_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::listTaskByDay(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;
	ptime time;
	Data::DataFeedback dataFeedback;

	time = parsedCommand.addStartTime;
	vector<Task> tasks;

	dataFeedback = _data.getByTime(tasks, time, time);

	emptyTasksVector(tasksVector);

	for( unsigned int i=0; i<tasks.size(); i++ ) {
		tasksVector.push_back(tasks[i]);
	}

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = LIST_SUCCESS_MESSAGE;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = LIST_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::listTaskByDate(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	
	string statusMessage;
	ptime time;
	Data::DataFeedback dataFeedback;

	time = parsedCommand.addStartTime;
	vector<Task> tasks;

	dataFeedback = _data.getByTime(tasks, time, time);

	emptyTasksVector(tasksVector);

	for( unsigned int i=0; i<tasks.size(); i++ ) {
		tasksVector.push_back(tasks[i]);
	}

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = LIST_SUCCESS_MESSAGE;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = LIST_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::listTaskNextWeek(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;
	Data::DataFeedback dataFeedback;
	
	// ptime t = parsedCommand.startTime + dd(7);
	// temporary ptime week;
	ptime week;

	vector<Task> tasks;
	dataFeedback = _data.getByTime(tasks, week, week);

	emptyTasksVector(tasksVector);

	for( unsigned int i=0; i<tasks.size(); i++ ) {
		tasksVector.push_back(tasks[i]);
	}

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = LIST_SUCCESS_MESSAGE;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = LIST_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::listTaskByMonth(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;
	ptime month;
	Data::DataFeedback dataFeedback;

	month = parsedCommand.addStartTime;
	vector<Task> tasks;

	dataFeedback = _data.getByTime(tasks, month, month);

	emptyTasksVector(tasksVector);

	for( unsigned int i=0; i<tasks.size(); i++ ) {
		tasksVector.push_back(tasks[i]);
	}

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = LIST_SUCCESS_MESSAGE;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = LIST_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::listTaskByDone(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;
	Data::DataFeedback dataFeedback;

	vector<Task> tasks;
	dataFeedback = _data.getByDone(tasks);

	emptyTasksVector(tasksVector);

	for( unsigned int i=0; i<tasks.size(); i++ ) {
		tasksVector.push_back(tasks[i]);
	}

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = LIST_SUCCESS_MESSAGE;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = LIST_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::clearTask() {
	
	string statusMessage;
	Data::DataFeedback dataFeedback;

	dataFeedback = _data.executeClear();

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = CLEAR_SUCCESS_MESSAGE;
		vector<Task> tasks;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = CLEAR_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::flagTaskByName(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	
	string statusMessage;
	string taskName;
	int taskId;
	int index;
	Data::DataFeedback dataFeedback;

	taskName = parsedCommand.addTaskName;
	index = parsedCommand.editTaskID;
	taskId = tasksVector[index].getTaskID();
	tasksVector[index].setPriority(PRIORITY_LEVEL_1);

	_task = tasksVector[index];

	dataFeedback = _data.executeEdit(_task, taskId);

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = FLAG_SUCCESS_MESSAGE;
		vector<Task> tasks;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = FLAG_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::flagTaskByIndex(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;
	int index;
	int taskID;
	Data::DataFeedback dataFeedback;

	index = parsedCommand.editTaskID;
	taskID = tasksVector[index].getTaskID();
	tasksVector[index].setPriority(PRIORITY_LEVEL_1);

	_task = tasksVector[index];

	dataFeedback = _data.executeEdit(_task, taskID);

	if( dataFeedback == Data::SUCCESS ) {
		statusMessage = FLAG_SUCCESS_MESSAGE;
		vector<Task> tasks;
		_data.getAll(tasks);
		_writer.write(tasks);
	} else {
		statusMessage = FLAG_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::sortTasksAlphabetically(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	
	string statusMessage;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;

	// sort UI's display
	sort(tasksVector.begin(), tasksVector.end(), sortObjAlpha);

	// get internal data
	dataFeedback = _data.getAll(tasks);

	if( dataFeedback == Data::SUCCESS ) {
		sort(tasks.begin(), tasks.end(), sortObjAlpha);
		_writer.write(tasks);
		_data.executeLoad(tasks);
		statusMessage = SORT_SUCCESS_MESSAGE;
	} else {
		statusMessage = SORT_ERROR_MESSAGE;
		logErrors(statusMessage, _undoState);
	}

	return statusMessage;
}

string Logic::sortTasksByFlag(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;
	Data::DataFeedback dataFeedback;
	vector<Task> tasks;



	return statusMessage;
}

string Logic::sortTasksByDateTime(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;


	return statusMessage;
}

string Logic::sortTasksByDone(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;


	return statusMessage;
}

string Logic::editTaskByName(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;


	return statusMessage;
}

string Logic::editTaskByTime(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;


	return statusMessage;
}

string Logic::editTaskByDateTime(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {
	
	string statusMessage;


	return statusMessage;
}

// sorting comparison functions for STL sort
bool Logic::sortAlpha(Task t1, Task t2) {
	return t1.getTaskName() < t2.getTaskName();
}

bool Logic::sortDateTime(Task t1, Task t2) {
	return t1.getStartTime() < t2.getStartTime();
}

// update state functions
void Logic::updateUndoState() {

	_undoState = _undoState++ % MAX_UNDO_STATES;

	_undoState0 = _writer;
	_undoState1 = _undoState0;
	_undoState2 = _undoState1;
	_undoState3 = _undoState2;
	_undoState4 = _undoState3;
	_undoState5 = _undoState4;
	_undoState6 = _undoState5;
	_undoState7 = _undoState6;
	_undoState8 = _undoState7;
	_undoState9 = _undoState8;
}

int Logic::getUndoState() {
	return _undoState;
}

string Logic::undo(Parser::PARSED_COMMAND parsedCommand, vector<Task>& tasksVector) {

	string statusMessage;

	return statusMessage;
}

// logging error messages
void Logic::logErrors(string errorMessage, int undoState) {
	fstream log;
	log.open(ERROR_LOG_FILE_NAME, fstream::in | fstream::app);

	log << errorMessage << endl;

	log.close();
}

// setup for when user first fires up program
void Logic::setupMainWriter() {
	_writer = Writer("test.txt");
}

void Logic::setInitUndoState(int initUndoState) {
	_undoState = initUndoState;
}

void Logic::setupWriters() {
	_undoState0 = Writer("test0.txt");
	_undoState1 = Writer("test1.txt");
	_undoState2 = Writer("test2.txt");
	_undoState3 = Writer("test3.txt");
	_undoState4 = Writer("test4.txt");
	_undoState5 = Writer("test5.txt");
	_undoState6 = Writer("test6.txt");
	_undoState7 = Writer("test7.txt");
	_undoState8 = Writer("test8.txt");
	_undoState9 = Writer("test9.txt");
}

// read and store in Data
void Logic::populateData() {
	
	vector<Task> initVector;

	_writer.read(initVector);
	_data.executeLoad(initVector);
}

// constants
// status messages
const string Logic::INVALID_COMMAND_MESSAGE = "Invalid Command";

const string Logic::ADD_SUCCESS_MESSAGE = "Task Added";
const string Logic::DELETE_SUCCESS_MESSAGE = "Task Deleted";
const string Logic::CLEAR_SUCCESS_MESSAGE = "File Contents Cleared";
const string Logic::LIST_SUCCESS_MESSAGE = "List Completed";
const string Logic::SORT_SUCCESS_MESSAGE = "Sort Completed";
const string Logic::EDIT_SUCCESS_MESSAGE = "Edit Completed";
const string Logic::SEARCH_SUCCESS_MESSAGE = "Search Completed";
const string Logic::FLAG_SUCCESS_MESSAGE = "Item Flagged";
const string Logic::UNFLAG_SUCCESS_MESSAGE = "Item Un-flagged";

const string Logic::ADD_ERROR_MESSAGE = "Unable To Add";
const string Logic::DELETE_ERROR_MESSAGE = "Unable To Delete";
const string Logic::CLEAR_ERROR_MESSAGE = "File Is Empty";
const string Logic::LIST_ERROR_MESSAGE = "Unable To List";
const string Logic::SORT_ERROR_MESSAGE = "Unable to sort";
const string Logic::EDIT_ERROR_MESSAGE = "Unable to edit";
const string Logic::FLAG_ERROR_MESSAGE = "Unable To Flag";
const string Logic::UNFLAG_ERROR_MESSAGE = "Unable to Un-flag";
const string Logic::NOT_FOUND_ERROR_MESSAGE = "Task Not Found";

// 5 priority levels
const int Logic::PRIORITY_LEVEL_1 = 1;
const int Logic::PRIORITY_LEVEL_2 = 2;
const int Logic::PRIORITY_LEVEL_3 = 3;
const int Logic::PRIORITY_LEVEL_4 = 4;
const int Logic::PRIORITY_LEVEL_5 = 5;

// number of undo states
const int Logic::INIT_UNDO_STATE = 0;
const int Logic::MAX_UNDO_STATES = 10;

// keywords
const string Logic::DELETE_TYPE_DONE = "done";

// error log file name
const string Logic::ERROR_LOG_FILE_NAME = "log.txt";

// helper functions
void Logic::emptyTasksVector(vector<Task>& tasksVector) {
	while( !tasksVector.empty() ) {
		tasksVector.pop_back();
	}
}